package com.song.druid.exception.hadler;

import com.song.druid.result.ResultEntity;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingPathVariableException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;

import java.util.List;
import java.util.stream.Collectors;

@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(BindException.class)
    public ResultEntity bindExceptionHandler(Exception e){
        BindException exception = (BindException) e;
        BindingResult bindingResult = exception.getBindingResult();
        String fields = getErrorField(bindingResult);
        List<String> messages = getErrorMessages(bindingResult);
        return ResultEntity.failCodeMessage(400, String.format("无效参数【%s】", fields)).setData(messages);
    }

    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResultEntity methodArgumentNotValidExceptionHandler(Exception e){
        MethodArgumentNotValidException exception = (MethodArgumentNotValidException) e;
        BindingResult bindingResult = exception.getBindingResult();
        String fields = getErrorField(bindingResult);
        List<String> messages = getErrorMessages(bindingResult);
        return ResultEntity.failCodeMessage(400, String.format("无效参数【%s】", fields)).setData(messages);
    }

    @ExceptionHandler(MissingServletRequestParameterException.class)
    public ResultEntity missingServletRequestParameterExceptionHandler(Exception e){
        MissingServletRequestParameterException exception = (MissingServletRequestParameterException) e;
        return ResultEntity.failCodeMessage(400, String.format("缺少参数【%s】", exception.getParameterName()));
    }

    @ExceptionHandler(MethodArgumentTypeMismatchException.class)
    public ResultEntity methodArgumentTypeMismatchExceptionHandler(Exception e){
        MethodArgumentTypeMismatchException exception = (MethodArgumentTypeMismatchException) e;
        return ResultEntity.failCodeMessage(400, String.format("参数【%s】类型不匹配", exception.getName()));
    }

    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    public ResultEntity httpRequestMethodNotSupportedExceptionHandler(Exception e){
        HttpRequestMethodNotSupportedException exception = (HttpRequestMethodNotSupportedException) e;
        return ResultEntity.failCodeMessage(400, String.format("HTTP请求方式【%s】不匹配", exception.getMethod()));
    }

    @ExceptionHandler(MissingPathVariableException.class)
    public ResultEntity missingPathVariableException(Exception e){
        MissingPathVariableException exception = (MissingPathVariableException) e;
        return ResultEntity.failCodeMessage(400, String.format("缺少路径参数【%s】", exception.getVariableName()));
    }

    /**
     * 获取异常字段
     * @param bindingResult
     * @return
     */
    public String getErrorField(BindingResult bindingResult){
        List<FieldError> errors = bindingResult.getFieldErrors();
        String fields = "";
        for (int i = 0; i < errors.size(); i++) {
            fields = fields + "," + errors.get(i).getField();
        }
        fields = fields.substring(1);
        return fields;
    }

    /**
     * 获取默认信息
     * @param bindingResult
     * @return
     */
    public List<String> getErrorMessages(BindingResult bindingResult){
        List<FieldError> errors = bindingResult.getFieldErrors();
        return errors.stream().map(FieldError::getDefaultMessage).collect(Collectors.toList());
    }
}
